home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dirut
/
ddir0789.zip
/
DDIR.ASM
next >
Wrap
Assembly Source File
|
1989-05-24
|
13KB
|
447 lines
;╔════════════════════════════════════════════════════════════╗
;║ DDIR.ASM -- Double Column Sorted DIR Command ║
;║ ──────── ║
;║ (C) Copyright Charles Petzold, 1985 ║
;║ DOS 4.x version (C) Copyright Roger M. Wilcox, 1989 ║
;║ COM file format ║
;╚════════════════════════════════════════════════════════════╝
CSEG Segment
Assume CS:CSEG, DS:CSEG
Org 002Ch ; Offset of Environment
Environment Label Byte
Org 007Bh ; Parameter for COMMAND.COM
NewParameter Label Byte
Org 0080h ; Parameter passed to program
OldParameter Label Byte
Org 0100h ; Entry point
Entry: Jmp Begin
; All Data
; --------
db '(C) Copyright Charles Petzold, 1985'
DosVersMsg db "Needs DOS 2.00 +$" ; Error messages
MemAllocMsg db "Memory Problem$"
CommandMsg db "COMMAND Problem$"
Comspec db "COMSPEC=" ; Search string in environment
CommandAsciiz dd ? ; Eventual pointer to COMMAND
ParamBlock dw ? ; Parameter Block for EXEC
dw NewParameter,? ; First ? must be replaced
dw 5Ch,? ; with Environment segment;
dw 6Ch,? ; others with this segment
OldInterrupt21 dd ? ; For vector address storage
BufferPtr dw Offset FileBuffer ; For storing files listing
CharCounter dw 0 ; Keeps track of characters
NowDoingFile db 0 ; Flagged for file printed
WithinFileList db 0 ; Flagged for file list
FileCounter dw 0 ; Keeps track of files
LineCounter db 0 ; For pausing at screen end
PauseMessage db 6 dup (205)," Press any key to continue "
db 6 dup (205),181
PauseMsgEnd Label Byte
; Check DOS Version
; -----------------
Begin: Mov AH,30h ; DOS Version function call
Int 21h ; Call DOS
Cmp AL,2 ; Check if version 2
Jae DosVersOK ; If equal or over, all OK
Mov DX,Offset DosVersMsg ; Wrong DOS version message
ErrorExit: Mov AH,9 ; Set up for string write
Int 21h ; Call DOS for message
Int 20h ; Dishonorable discharge
; Adjust stack and un-allocate rest of memory
; -------------------------------------------
DosVersOK: Mov DI,Offset FileBuffer ; Place to save files
Mov CX,528 * 39 ; Allow room for 528 files
Mov AL,' ' ; Will clear with blanks
Cld ; Forward direction
Rep Stosb ; Clear the area
Mov BX,(Offset FileBuffer) + (528 * 39) + 100h
; New end of program
Mov SP,BX ; Set the stack pointer
Add BX,15 ; Add 15 for rounding
Mov CL,4 ; Number of shifts
Shr BX,CL ; Convert AX to segment
Mov AH,4Ah ; DOS call to shrink down
Int 21h ; allocated memory
Mov DX,Offset MemAllocMsg ; Possible error message
Jc ErrorExit ; Only print it if Carry set
; Search for Comspec in Environment
; ---------------------------------
Mov ES,[Environment] ; Environment Segment
Sub DI,DI ; Start search at beginning
Cld ; String increment to forward
TryThis: Cmp Byte Ptr ES:[DI],0 ; See if end of environment
Jz NoFindComSpec ; If so, we have failed
Push DI ; Save environment pointer
Mov SI,Offset ComSpec ; String to search for
Mov CX,8 ; Characters in search string
Repz Cmpsb ; Check if strings are same
Pop DI ; Get back the pointer
Jz FoundComspec ; Found string only zero flag
Sub AL,AL ; Zero out AL
Mov CX,8000h ; Set for big search
Repnz Scasb ; Find the next zero in string
Jmp TryThis ; And do the search from there
NoFindComSpec: Mov DX,Offset CommandMsg ; Message for COMSPEC error
Jmp ErrorExit ; Print it and exit
FoundComspec: Add DI,8 ; So points after 'COMSPEC='
Mov Word Ptr [CommandASCIIZ],DI ; Save the address of
Mov Word Ptr [CommandASCIIZ + 2],ES ; COMMAND ASCIIZ
; Set up parameter block for EXEC call
; ------------------------------------
Mov [ParamBlock],ES ; Segment of Environment string
Mov [ParamBlock + 4],CS ; Segment of this program
Mov [ParamBlock + 8],CS ; so points to FCB's
Mov [ParamBlock + 12],CS ; and NewParameter
; Save and set Interrupt 21h vector address
; -----------------------------------------
Mov AX,3521h ; DOS call to get Interrupt 21
Int 21h ; vector address
Mov Word Ptr [OldInterrupt21],BX ; Save offset
Mov Word Ptr [OldInterrupt21 + 2],ES ; And segment
Mov DX,Offset NewInterrupt21; Address of new Interrupt 21
Mov AX,2521h ; Do DOS call to
Int 21h ; set the new address
; Fix up new parameter for "/C DIR" String
; ----------------------------------------
Mov AL,[OldParameter] ; Number of parameter chars
Add AL,5 ; We'll be adding five more
Mov [NewParameter],AL ; Save it
Mov Word Ptr [NewParameter + 1],'C/' ; i.e. "/C"
Mov Word Ptr [NewParameter + 3],'ID' ; Then "DI"
Mov Byte Ptr [NewParameter + 5],'R' ; And "R"
; Load COMMAND.COM
; ----------------
Push CS ; Push this segment so we can
Pop ES ; set ES to it
Mov BX,Offset ParamBlock ; ES:BX = address of block
Lds DX,[CommandAsciiz] ; DS:DX = address of ASCIIZ
Mov AX,4B00h ; EXEC call 4Bh, type 0
Int 21h ; Load command processor
; Return from COMMAND.COM
; -----------------------
Mov AX,CS ; Get this segment in AX
Mov DS,AX ; Set DS to it
Mov SS,AX ; And SS for stack segment
Mov SP,(Offset FileBuffer) + (528 * 39) + 100h
; Set Stack again
PushF ; Save Carry for error check
Push DS ; Save DS during next call
Mov DX,Word Ptr [OldInterrupt21] ; Old Int 21 offset
Mov DS,Word Ptr [OldInterrupt21 + 2]; and segment
Mov AX,2521h ; Call DOS to set vector
Int 21h ; address to original
Pop DS ; Restore DS to this segment
PopF ; Get back Carry flage
Jnc NormalEnd ; Continue if no error
Mov DX,Offset CommandMsg ; Otherwise we'll print error
Jmp ErrorExit ; message and exit
NormalEnd: Int 20h ; Terminate program
; New Interrupt 21h
; -----------------
NewInterrupt21 Proc Far
Sti ; Allow further interrupts
Cmp AH,40h ; Check if file / device write
Je CheckHandle ; If so, continue checks
SkipIntercept: Jmp CS:[OldInterrupt21] ; Just jump to old interrupt
CheckHandle: Cmp BX,1 ; Check if standard output
Jne SkipIntercept ; Not interested if not
PushF ; Push all registers that
Push AX ; we'll be messing with
Push CX
Push SI
Push DI
Push ES
Push CS ; Push the code segment
Pop ES ; So we can set ES to it
Cld ; Forward for string transfers
Mov SI,DX ; Now DS:SI = text source
Mov DI,CS:[BufferPtr] ; And ES:DI = text destination
Cmp CX,2 ; See if two chars to write
Jne RegularChars ; If not, can't be CR/LF
Cmp Word Ptr DS:[SI],0A0Dh ; See if CR/LF being written
Jne RegularChars ; Skip rest if not CR/LF
Mov CX,CS:[CharCounter] ; Get characters in line
Mov CS:[CharCounter],0 ; Start at new line
Cmp CS:[NowDoingFile],1 ; See if CR/LF terminates file
Jnz Kludge ; If not, just write to screen
Mov AX,39 ; Max characters per line
Sub AX,CX ; Subtract those passed
Add CS:[BufferPtr],AX ; Kick up pointer by that
Mov CS:[NowDoingFile],0 ; Finished with file
Jmp PopAndReturn ; So just return to COMMAND
Kludge: JMP AllowTransfer
RegularChars: Add CS:[CharCounter],CX ; Kick up counter by number
Cmp CS:[CharCounter],CX ; See if beginning of line
Jne NotLineBegin ; If not, must be in middle
Cmp Byte Ptr DS:[SI],' ' ; See if first char is blank
Je Cont ; If so, it ain't a file line
CMP WORD PTR DS:[SI],'oV' ; Vo(lume ...)
JE Cont
CMP WORD PTR DS:[SI],'iD' ; Di(rectory of ...)
JNE ItsAFile
Cont: Cmp CS:[WithinFileList],1 ; See if doing file listing
Jne AllowTransfer ; If not, just print stuff
Call SortAndList ; Files done -- sort and list
Mov CS:[WithinFileList],0 ; Not doing files now
Jmp Short AllowTransfer ; So just print the stuff
ItsAFile: Cmp CS:[FileCounter],528 ; See if 11 buffer filled up
Jb NotTooManyFiles ; If not just continue
Push CX ; Otherwise, save this register
Call SortAndList ; Print all up to now
Mov CS:[FileCounter],0 ; Reset the counter
Mov DI